#include "face_encrypt.h"
#include <string.h>

#if defined(AES_DEBUG)
#define FACE_ENC_LOG(format, ...) OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#define __FACE_ENC_LOG(format, ...) __OSAL_LOG(C_CYAN format C_NONE, ##__VA_ARGS__)
#else
#define FACE_ENC_LOG(format, ...)
#define __FACE_ENC_LOG(format, ...)
#endif

#define SIZE_OF_RANGDOM_NUM 4 //随机数个数

const uint8_t faceKeyIndex[FACE_KEY_SIZE] = {31, 28, 25, 22, 19, 16, 13, 10, 21, 18, 15, 12, 9, 6, 3, 0}; //Md5 32位转为16位的取值逻辑数组

uint16_t header_flag = 0xaaef;
static uint8_t mEncKey[FACE_KEY_SIZE];									   //AES密钥
static uint8_t encryptionFlag = 0;										   //加密模式   0：不加密     1：加密

/*加密*/
#define ID_FILL_NUM 0x00			//被加密数据个数不是AES_KEY_LENGTH整数不足位数的填充值
#define AES128_ENCRYPTION_LENGTH 16 //AES加密的密钥长度 可选长度  16  24   32
#define MAX_AES_DATA_LEN 64			//加密密钥最大长度

#define MAX_ARRAY_ROW (MAX_AES_DATA_LEN / AES128_ENCRYPTION_LENGTH) //二维数组行数

/**
  * @brief  AES加密
  * @note
  *
  * @param cryptoMode:加解密方式    
  * @param AESBlock_count:带加密的组数  16个字节位一组
  * @param  AESECBmsg：待加密内容
  * @param  AESECBresult：加密结果
  * @param  AESKey:钥
  */
static ErrorStatus Aes128Encrypt(uint8_t cryptoMode, uint16_t AESBlock_count, uint8_t *src, uint8_t *dst, uint8_t *AESKey)
{
	int8_t ret;
	Crypto_enum_t mode = (cryptoMode ? AES128_ENCRYPTION : AES128_DECRYPTION);
	ret = Device_Crypto(mode, src, AESBlock_count * 16, dst, AESKey);

	uint8_t i = 0;
	uint8_t num = AES128_ENCRYPTION_LENGTH * AESBlock_count;

	const char *enc_text = "enc ->";
	const char *dec_test = "dec <-";
	char *out = (cryptoMode ? (char *)enc_text : (char *)dec_test);

	__FACE_ENC_LOG("key: ");
	for (i = 0; i < AES128_ENCRYPTION_LENGTH; i++)
	{
		__FACE_ENC_LOG("%x ", AESKey[i]);
		if ((i + 1) % AES128_ENCRYPTION_LENGTH == 0)
			__FACE_ENC_LOG("\r\n");
	}

	__FACE_ENC_LOG("src %s: ", out);
	for (i = 0; i < num; i++)
	{
		__FACE_ENC_LOG("%x ", src[i]);
		if ((i + 1) % AES128_ENCRYPTION_LENGTH == 0)
			__FACE_ENC_LOG("\r\n");
	}

	__FACE_ENC_LOG("rslt %s: ", out);
	for (i = 0; i < num; i++)
	{

		__FACE_ENC_LOG("%x ", dst[i]);
		if ((i + 1) % AES128_ENCRYPTION_LENGTH == 0)
			__FACE_ENC_LOG("\r\n");
	}

	return (ret == 0 ? SUCCESS : ERROR);
}

/**
  * @brief  数据aes加密并输出加密后的数值

  * @param EncryptDirMode:加解密模式    1：加密     0:解密
  * @param  AesKey：aes加密密钥，默认为16字节
  * @param  input：待加密数据指针
  * @param  inputLen：待加密数据长度
  * @param  result：加密结果
  * @param  resultLen:需要获得的加密结果长度
  * @note   目前支持64位长度加密，如需增加加密长度，需要更改密钥值和加密密钥长度
  */
ErrorStatus Aes_Encrypt_Decrypt(uint8_t EncryptDirMode, uint8_t *AesKey, uint8_t *input, const uint16_t *inputLen, uint8_t *result, uint16_t *resultLen)
{
	ErrorStatus ret;
	uint8_t AESResult_buf[MAX_ARRAY_ROW][AES128_ENCRYPTION_LENGTH]; //加密结果缓存
	uint8_t AESESBmsg_buf[MAX_ARRAY_ROW][AES128_ENCRYPTION_LENGTH]; //待加密内容缓存
	uint16_t AESESBmsgRow = 0;										//待加密行数
	uint16_t AESESBmsgRemainder = 0;								//待加密余数
	AESESBmsgRow = *inputLen / AES128_ENCRYPTION_LENGTH;
	AESESBmsgRemainder = *inputLen % AES128_ENCRYPTION_LENGTH;
	memcpy(&AESESBmsg_buf[0][0], input, *inputLen); //复制加密内容
	if (AESESBmsgRemainder != 0)
	{
		memset(&AESESBmsg_buf[AESESBmsgRow][AESESBmsgRemainder], ID_FILL_NUM, AES128_ENCRYPTION_LENGTH - AESESBmsgRemainder); //不足位数填充
		AESESBmsgRow++;
	}
	ret = Aes128Encrypt(EncryptDirMode, AESESBmsgRow, &AESESBmsg_buf[0][0], &AESResult_buf[0][0], AesKey);
	*resultLen = AESESBmsgRow * AES128_ENCRYPTION_LENGTH;
	memcpy(&result[0], &AESResult_buf[0][0], *resultLen); //复制加密内
	return ret;
}

/***********************************************密钥生成*********************************************/

/**
  * @brief  生成四字节真随机数
  * @note   
  *         
  * @param  pRandom：随机数缓存区（指向的存储空间必须要有4个字节）
  */
void FaceEncrypt_GenerateRandomNumber(uint8_t *pRandom)
{
	Device_Crypto(CALC_RANDOM_NUMBER, NULL, SIZE_OF_RANGDOM_NUM, pRandom, NULL);
	FACE_ENC_LOG("\r\n FaceEncrypt_GenerateRandomNumber:\r\n");
	for (int i = 0; i < SIZE_OF_RANGDOM_NUM; i++)
	{
		__FACE_ENC_LOG("%#2x ", pRandom[i]);
	}
}

/**
  * @brief  加密标志设置
  * @note   
  *         
  * @param mode: 0：不加密     1：加密  
  */
void FaceEncrypt_Set_EnFlag(uint8_t flag)
{
	encryptionFlag = flag;
}

/**
  * @brief  加密标志获取
  * @note   
  *         
  * @param mode: 0：不加密     1：加密
  */
uint8_t FaceEncrypt_Get_EnFlag(void)
{
	return encryptionFlag;
}

/**
  * @brief  生成aes加密密钥
  * @note   
  *         
  * @param  pRandom：随机数缓存区（指向的存储空间必须要有8个字节）
  */
void FaceEncrypt_GenencKey(uint8_t *pRandom)
{
	uint32_t i = 0, j = 0;
	//MCU发送0x53/0x52指令：设定密钥选取规则0~15
	//uint32_t faceKeyIndex[FACE_KEY_SIZE] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
	//uint32_t faceKeyIndex[FACE_KEY_SIZE] = {27, 4, 3, 0, 11, 15, 9, 19, 12, 13, 1, 8, 23, 7, 2, 31};

	//MCU发送0x50指令：4Bytes随机数(十六进制)
	//uint8_t random[RANDOM_SIZE] = {0x3C, 0x56, 0xB3, 0x85};
	//uint8_t random[RANDOM_SIZE] = {0x85, 0x12, 0x21, 0x23};
	//uint8_t random[RANDOM_SIZE] = {0xAD, 0xBF, 0x29, 0xD8};
	//uint8_t random[RANDOM_SIZE] = {0x31, 0x32, 0x33, 0x34};
	uint8_t str[RANDOM_SIZE + 1];

	// 生成的md5
	uint8_t md5str[FACE_KEY_SIZE];
	uint8_t md5chr[FACE_KEY_SIZE * 2];
	__FACE_ENC_LOG("\r\n random before:");
	for (i = 0; i < RANDOM_SIZE + 1; i++)
	{
		__FACE_ENC_LOG("%4x", pRandom[i]);
	}

	memcpy(str, pRandom, RANDOM_SIZE);
	str[RANDOM_SIZE] = '\0';

	__FACE_ENC_LOG("\r\n random after:");
	for (i = 0; i < RANDOM_SIZE + 1; i++)
	{
		__FACE_ENC_LOG("%4x", str[i]);
	}

	Device_Crypto(CALC_MD5, str, SIZE_OF_RANGDOM_NUM, md5str, NULL);

	__FACE_ENC_LOG("\r\nmd5:");
	for (i = 0; i < FACE_KEY_SIZE; i++)
	{
		__FACE_ENC_LOG("%2x", md5str[i]);
	}
	__FACE_ENC_LOG("\n");
	// 按照设定的密钥选取规则取密钥
	for (i = 0; i < 16; i++)
	{
		md5chr[j] = (md5str[i] & 0xf0) >> 4;
		md5chr[j + 1] = (md5str[i] & 0x0f);
		j = j + 2;
	}

	for (i = 0; i < FACE_KEY_SIZE; i++)
	{
		if (md5chr[faceKeyIndex[i]] < 10)
		{
			mEncKey[i] = md5chr[faceKeyIndex[i]] + '0';
		}
		else if (md5chr[faceKeyIndex[i]] < 16)
		{
			mEncKey[i] = md5chr[faceKeyIndex[i]] - 10 + 'a';
		}
		else
		{
		}
	}

	FACE_ENC_LOG("key: %16s\n", mEncKey);
}

/**
  * @brief  商汤数据解密并输出解密后的数值
  * @note
  *
  * @param EncryptDirMode:加解密模式    1：加密     0:解密
  * @param  input：待加密数据指针		地址从mid开始
  * @param  inputLen：待加密数据长度            
  * @note   目前支持最长64位长度加密，如需增加加密长度，需要更改密钥值和加密密钥长度
  */
void FaceEncrypt_SenseTime_Encrypt_Decrypt(uint8_t EncryptDirMode, uint8_t *input, const uint16_t *inputLen, uint8_t *result, uint16_t *resultLen)
{
	if (*inputLen > MAX_AES_DATA_LEN)
	{
		FACE_ENC_LOG("encrypt decrypt error:input leng too long\r\n");
		return;
	}
	if (1 == FaceEncrypt_Get_EnFlag()) //加解密模式
	{
		Aes_Encrypt_Decrypt(EncryptDirMode, mEncKey, input, inputLen, result, resultLen);
	}
}
